package com.ls.datalog.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.assertj.core.util.Lists;

import com.google.common.collect.Maps;
import com.ls.datalog.domain.ChangeItem;
import com.ls.datalog.domain.ZhName;

public class DiffUtils {

	/**
	 * 基于当前dao bean对象，执行findbyId，获取实例
	 * @param target
	 * @param valueOf
	 * @return
	 */
	public static Object findById(Object target, Long id) {
		try {
			Method method = target.getClass().getDeclaredMethod("findById", Long.class);
			Object oldValue = method.invoke(target, id);
			return oldValue;
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return null;
	}

	/**
	 * 获取插入对象的changItem，就是该对象的所有字段
	 * @param obj
	 * @return
	 * @throws Exception 
	 */
	public static List<ChangeItem> getInsertChangeItems(Object obj) throws Exception {
		Map<String,String> maps;
		Map<String,String> maps2;
		maps = getBeanProperties(obj,true);
		maps2 = getZhName(obj.getClass());
		List<ChangeItem> items = Lists.newArrayList();
		ChangeItem item;
		for(Map.Entry<String, String> entry:maps.entrySet()) {
			if(null == entry.getValue())
				continue;
			item=new ChangeItem();
			item.setField(entry.getKey());
			item.setFieldName(maps2.get(entry.getKey())==null?entry.getKey():maps2.get(entry.getKey()));
			item.setNewValue(entry.getValue());
			item.setOldValue(null);
			items.add(item);
		}
		return items;
	}
	
	/**
	 * 获取字段的中文名
	 * @param clz
	 * @return
	 */
	public static Map<String,String> getZhName(Class clz){
		Map<String,String> maps = Maps.newHashMap();
		 ZhName[] names;
		for(Field f: clz.getDeclaredFields()) {
			names = f.getAnnotationsByType(ZhName.class);
			if(names!=null&&names.length>0) {
				maps.put(f.getName(), names[0].value());
			}
		}
		
		return maps;
	}
	
	public static Map<String,String> getBeanProperties(Object obj,boolean saveNull) throws Exception{
		Map<String,String> maps = Maps.newHashMap();
		Class clz = obj.getClass();
		Method method;
		String name;
		Object value = null;
		for(Field f: clz.getDeclaredFields()) {
			if(isBaseDataType(f.getType())) {
				name = f.getName();
				method = clz.getMethod("get"+name.substring(0,1).toUpperCase()+name.substring(1), null);
				value = method.invoke(obj, null);
				if(saveNull||value!=null)
				maps.put(name, getFieldStringValue(f.getType(),value));
			}
		}
		return maps;
	}
    /**
     * 自定义不同类型的string值
     * @param type
     * @return
     */
    public static String getFieldStringValue(Class type,Object value){
    	if(value==null)
    		return null;
        if(type.equals(Date.class)){
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return formatter.format((Date)value);
        }
        return value.toString();
    }
	/**
     * 判断一个类是否为基本数据类型或包装类，或日期。
     * @param clazz 要判断的类。
     * @return true 表示为基本数据类型。
     */
    public static boolean isBaseDataType(Class clazz) throws Exception {
        return
                (
                        clazz.equals(String.class) ||
                                clazz.equals(Integer.class) ||
                                clazz.equals(Byte.class) ||
                                clazz.equals(Long.class) ||
                                clazz.equals(Double.class) ||
                                clazz.equals(Float.class) ||
                                clazz.equals(Character.class) ||
                                clazz.equals(Short.class) ||
                                clazz.equals(BigDecimal.class) ||
                                clazz.equals(BigInteger.class) ||
                                clazz.equals(Boolean.class) ||
                                clazz.equals(Date.class) ||
                                clazz.isPrimitive()
                );
    }

	public static List<ChangeItem> getDeleteChangeItems(Object obj) throws Exception {
		 List<ChangeItem> items = getInsertChangeItems(obj);
		 for(ChangeItem item:items) {
			 item.setOldValue(item.getNewValue());
			 item.setNewValue(null);
		 }	
		return items;
	}

	public static List<ChangeItem> getUpdateChangeItems(Object oldObj, Object newObj) throws Exception {
		Map<String,String> oldMaps;
		Map<String,String> newMaps;
		Map<String,String> maps2;
		oldMaps = getBeanProperties(oldObj,true);
		newMaps = getBeanProperties(newObj,true);
		maps2 = getZhName(oldObj.getClass());
		List<ChangeItem> items = Lists.newArrayList();
		ChangeItem item;
		Object oldValue;
		Object newValue;
		for(Map.Entry<String, String> entry:oldMaps.entrySet()) {
			oldValue = entry.getValue();
			newValue = newMaps.get(entry.getKey());
			if((oldValue!=null&&!oldValue.equals(newValue))||(newValue!=null&&!newValue.equals(oldValue))){
				item=new ChangeItem();
				item.setField(entry.getKey());
				item.setFieldName(maps2.get(entry.getKey())==null?entry.getKey():maps2.get(entry.getKey()));
				item.setNewValue(getFieldStringValue(newValue.getClass(), newValue));
				item.setOldValue(getFieldStringValue(oldValue.getClass(), oldValue));
				items.add(item);
			}
		}
		return items;
	}
}
